﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace FindProject.Common
{
    internal static class SvnHelper
    {
        /// <summary>
        /// 从SVN仓库搜索项目
        /// </summary>
        /// <param name="searchKeyword">搜索关键字</param>
        /// <returns>匹配的项目列表</returns>
        internal static async Task<List<SvnProjectInfo>> SearchProjectsFromSvnAsync(string searchKeyword)
        {
            var results = new List<SvnProjectInfo>();

            if (AppConfig.Options.SvnConfig.SvnRepositories == null ||
                !AppConfig.Options.SvnConfig.SvnRepositories.Any())
            {
                return results;
            }

            // 首先检查SVN是否可用
            if (!await IsSvnAvailableAsync())
            {
                throw new Exception("SVN客户端不可用。请确保已安装SVN并配置正确的执行路径。");
            }

            foreach (var repository in AppConfig.Options.SvnConfig.SvnRepositories)
            {
                try
                {
                    var repositoryResults = await SearchInRepositoryAsync(repository, searchKeyword);
                    results.AddRange(repositoryResults);
                }
                catch (Exception ex)
                {
                    // 记录错误但不中断其他仓库的搜索
                    System.Diagnostics.Debug.WriteLine($"搜索SVN仓库失败: {repository}, 错误: {ex.Message}");
                    throw new Exception($"搜索SVN仓库失败: {repository}\n错误详情: {ex.Message}");
                }
            }

            return results;
        }

        /// <summary>
        /// 检查SVN是否可用
        /// </summary>
        /// <returns>SVN是否可用</returns>
        private static async Task<bool> IsSvnAvailableAsync()
        {
            try
            {
                var svnPath = GetSvnExecutablePath();
                var command = $"{svnPath} --version";
                await ExecuteSvnCommandAsync(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 获取SVN可执行文件路径
        /// </summary>
        /// <returns>SVN可执行文件路径</returns>
        private static string GetSvnExecutablePath()
        {
            var configuredPath = AppConfig.Options.SvnConfig.SvnExecutablePath;

            // 如果配置了完整路径，直接使用
            if (!string.IsNullOrEmpty(configuredPath) && Path.IsPathFullyQualified(configuredPath))
            {
                return $"\"{configuredPath}\"";
            }

            // 如果只配置了文件名或者为空，尝试常见的路径
            var commonPaths = new[]
            {
                configuredPath ?? "svn",
                @"C:\Program Files\TortoiseSVN\bin\svn.exe",
                @"C:\Program Files (x86)\TortoiseSVN\bin\svn.exe",
                @"C:\Program Files\SlikSvn\bin\svn.exe",
                @"C:\Program Files (x86)\SlikSvn\bin\svn.exe",
                @"C:\Program Files\VisualSVN Server\bin\svn.exe"
            };

            foreach (var path in commonPaths)
            {
                if (File.Exists(path))
                {
                    return $"\"{path}\"";
                }
            }

            // 如果都找不到，就使用配置的路径（可能在PATH中）
            return configuredPath ?? "svn";
        }

        /// <summary>
        /// 在特定SVN仓库中搜索项目
        /// </summary>
        /// <param name="repositoryUrl">SVN仓库URL</param>
        /// <param name="searchKeyword">搜索关键字</param>
        /// <returns>匹配的项目列表</returns>
        private static async Task<List<SvnProjectInfo>> SearchInRepositoryAsync(string repositoryUrl, string searchKeyword)
        {
            var results = new List<SvnProjectInfo>();

            // 获取SVN仓库的目录列表
            var directories = await GetSvnDirectoriesAsync(repositoryUrl);
            var repositoryName = GetRepositoryDisplayName(repositoryUrl);

            foreach (var directory in directories)
            {
                if (directory.Name.Contains(searchKeyword, StringComparison.OrdinalIgnoreCase))
                {
                    results.Add(new SvnProjectInfo
                    {
                        ProjectName = directory.Name,
                        SvnUrl = directory.Url,
                        Repository = repositoryUrl,
                        RepositoryName = repositoryName,
                        LastModified = directory.LastModified
                    });
                }
            }

            return results;
        }

        private static string GetRepositoryDisplayName(string repositoryUrl)
        {
            if (string.IsNullOrWhiteSpace(repositoryUrl))
            {
                return "SVN 仓库";
            }

            var trimmed = repositoryUrl.TrimEnd('/', '\\');
            var index = trimmed.LastIndexOfAny(new[] { '/', '\\' });
            if (index >= 0 && index < trimmed.Length - 1)
            {
                return trimmed[(index + 1)..];
            }

            return trimmed;
        }

        /// <summary>
        /// 获取SVN仓库的目录列表
        /// </summary>
        /// <param name="repositoryUrl">SVN仓库URL</param>
        /// <returns>目录信息列表</returns>
        private static async Task<List<SvnDirectoryInfo>> GetSvnDirectoriesAsync(string repositoryUrl)
        {
            var directories = new List<SvnDirectoryInfo>();

            try
            {
                var svnCommand = BuildSvnListCommand(repositoryUrl);
                var output = await ExecuteSvnCommandAsync(svnCommand);

                directories = ParseSvnListOutput(output, repositoryUrl);
            }
            catch (Exception ex)
            {
                throw new Exception($"获取SVN目录列表失败: {ex.Message}", ex);
            }

            return directories;
        }

        /// <summary>
        /// 构建SVN list命令
        /// </summary>
        /// <param name="repositoryUrl">SVN仓库URL</param>
        /// <returns>SVN命令</returns>
        private static string BuildSvnListCommand(string repositoryUrl)
        {
            var svnPath = GetSvnExecutablePath();
            var command = new StringBuilder();

            // 设置环境变量来确保SVN输出使用正确的编码
            command.Append($"{svnPath} list \"{repositoryUrl}\"");

            if (!string.IsNullOrEmpty(AppConfig.Options.SvnConfig.Username))
            {
                command.Append($" --username \"{AppConfig.Options.SvnConfig.Username}\"");
            }

            if (!string.IsNullOrEmpty(AppConfig.Options.SvnConfig.Password))
            {
                command.Append($" --password \"{AppConfig.Options.SvnConfig.Password}\"");
            }

            command.Append(" --non-interactive --trust-server-cert");

            return command.ToString();
        }

        /// <summary>
        /// 执行SVN命令
        /// </summary>
        /// <param name="command">命令</param>
        /// <returns>命令输出</returns>
        private static async Task<string> ExecuteSvnCommandAsync(string command)
        {
            try
            {
                // 从配置中获取编码设置
                var encodings = GetConfiguredEncodings();

                Exception? lastException = null;

                foreach (var encoding in encodings)
                {
                    try
                    {
                        var processInfo = new ProcessStartInfo("cmd.exe", $"/c \"{command}\"")
                        {
                            CreateNoWindow = true,
                            UseShellExecute = false,
                            RedirectStandardOutput = true,
                            RedirectStandardError = true,
                            StandardOutputEncoding = encoding,
                            StandardErrorEncoding = encoding
                        };

                        using var process = Process.Start(processInfo);
                        if (process == null)
                            throw new Exception("无法启动SVN进程");

                        var outputTask = process.StandardOutput.ReadToEndAsync();
                        var errorTask = process.StandardError.ReadToEndAsync();

                        await process.WaitForExitAsync();

                        var output = await outputTask;
                        var error = await errorTask;

                        if (process.ExitCode != 0)
                        {
                            var errorMessage = $"SVN命令执行失败 (退出代码: {process.ExitCode})";
                            if (!string.IsNullOrEmpty(error))
                            {
                                errorMessage += $"\n错误信息: {error}";
                            }
                            if (!string.IsNullOrEmpty(output))
                            {
                                errorMessage += $"\n输出信息: {output}";
                            }
                            errorMessage += $"\n执行的命令: {command}";
                            errorMessage += $"\n使用编码: {encoding.EncodingName}";

                            throw new Exception(errorMessage);
                        }

                        // 检查输出是否包含乱码（简单的启发式检查）
                        if (IsValidChineseText(output))
                        {
                            System.Diagnostics.Debug.WriteLine($"SVN命令成功执行，使用编码: {encoding.EncodingName}");
                            return output;
                        }

                        // 如果没有中文内容，直接返回
                        if (!ContainsChineseCharacters(output))
                        {
                            System.Diagnostics.Debug.WriteLine($"SVN命令成功执行，无中文内容，使用编码: {encoding.EncodingName}");
                            return output;
                        }

                        System.Diagnostics.Debug.WriteLine($"编码 {encoding.EncodingName} 产生乱码，尝试下一个编码");
                    }
                    catch (Exception ex)
                    {
                        lastException = ex;
                        System.Diagnostics.Debug.WriteLine($"使用编码 {encoding.EncodingName} 执行失败: {ex.Message}");
                        // 继续尝试下一种编码
                        continue;
                    }
                }

                // 如果所有编码都失败了，抛出最后一个异常
                throw lastException ?? new Exception("所有编码尝试都失败了");
            }
            catch (Exception ex)
            {
                throw new Exception($"执行SVN命令时发生异常: {ex.Message}\n命令: {command}", ex);
            }
        }

        /// <summary>
        /// 从配置中获取编码列表
        /// </summary>
        /// <returns>编码列表</returns>
        private static List<Encoding> GetConfiguredEncodings()
        {
            var encodings = new List<Encoding>();
            var config = AppConfig.Options.SvnConfig;

            try
            {
                // 添加主要编码（从配置中读取，默认UTF-8）
                var primaryEncoding = GetEncodingByName(config.OutputEncoding ?? "UTF-8");
                if (primaryEncoding != null)
                {
                    encodings.Add(primaryEncoding);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"无法解析主要编码 '{config.OutputEncoding}': {ex.Message}");
            }

            // 如果没有任何编码被成功添加，使用默认的UTF-8编码
            if (encodings.Count == 0)
            {
                System.Diagnostics.Debug.WriteLine("配置的编码无效，使用默认UTF-8编码");
                encodings.Add(Encoding.UTF8);
            }

            return encodings;
        }

        /// <summary>
        /// 根据编码名称获取编码对象
        /// </summary>
        /// <param name="encodingName">编码名称</param>
        /// <returns>编码对象</returns>
        private static Encoding? GetEncodingByName(string encodingName)
        {
            if (string.IsNullOrWhiteSpace(encodingName))
                return null;

            try
            {
                return encodingName.ToUpperInvariant() switch
                {
                    "UTF-8" or "UTF8" => Encoding.UTF8,
                    "GB2312" => Encoding.GetEncoding("GB2312"),
                    "GBK" => Encoding.GetEncoding("GBK"),
                    "ASCII" => Encoding.ASCII,
                    "UNICODE" or "UTF-16" => Encoding.Unicode,
                    "DEFAULT" => Encoding.Default,
                    _ => Encoding.GetEncoding(encodingName)
                };
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 检查文本是否包含中文字符
        /// </summary>
        /// <param name="text">要检查的文本</param>
        /// <returns>是否包含中文字符</returns>
        private static bool ContainsChineseCharacters(string text)
        {
            if (string.IsNullOrEmpty(text))
                return false;

            foreach (char c in text)
            {
                if (c >= 0x4e00 && c <= 0x9fbb) // 中文字符的Unicode范围
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 简单检查中文文本是否有效（不是乱码）
        /// </summary>
        /// <param name="text">要检查的文本</param>
        /// <returns>文本是否有效</returns>
        private static bool IsValidChineseText(string text)
        {
            if (string.IsNullOrEmpty(text))
                return true; // 空文本认为是有效的

            // 如果没有中文字符，认为是有效的
            if (!ContainsChineseCharacters(text))
                return true;

            // 检查是否包含常见的乱码字符
            var garbledChars = new[] { '?', '�', '锘' };
            var chineseCharCount = 0;
            var garbledCharCount = 0;

            foreach (char c in text)
            {
                if (c >= 0x4e00 && c <= 0x9fbb)
                {
                    chineseCharCount++;
                }
                else if (garbledChars.Contains(c))
                {
                    garbledCharCount++;
                }
            }

            // 如果乱码字符比例过高，认为是无效的
            if (chineseCharCount > 0)
            {
                double garbledRatio = (double)garbledCharCount / chineseCharCount;
                return garbledRatio < 0.3; // 乱码比例小于30%认为是有效的
            }

            return true;
        }

        /// <summary>
        /// 解析SVN list命令的输出
        /// </summary>
        /// <param name="output">命令输出</param>
        /// <param name="repositoryUrl">仓库URL</param>
        /// <returns>目录信息列表</returns>
        private static List<SvnDirectoryInfo> ParseSvnListOutput(string output, string repositoryUrl)
        {
            var directories = new List<SvnDirectoryInfo>();

            if (string.IsNullOrWhiteSpace(output))
                return directories;

            var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var line in lines)
            {
                var trimmedLine = line.Trim();
                if (string.IsNullOrWhiteSpace(trimmedLine))
                    continue;

                // SVN中目录以/结尾
                if (trimmedLine.EndsWith("/"))
                {
                    var dirName = trimmedLine.TrimEnd('/');

                    // 跳过空的目录名
                    if (string.IsNullOrWhiteSpace(dirName))
                        continue;

                    directories.Add(new SvnDirectoryInfo
                    {
                        Name = dirName,
                        Url = $"{repositoryUrl.TrimEnd('/')}/{dirName}",
                        LastModified = DateTime.Now // 简化处理，实际可以解析详细信息
                    });
                }
            }

            return directories;
        }

        /// <summary>
        /// 检出SVN项目到本地
        /// </summary>
        /// <param name="svnUrl">SVN项目URL</param>
        /// <param name="localPath">本地路径</param>
        /// <returns>是否成功</returns>
        internal static async Task<bool> CheckoutProjectAsync(string svnUrl, string localPath)
        {
            try
            {
                var svnPath = GetSvnExecutablePath();
                var command = new StringBuilder();

                // 设置环境变量来确保SVN输出使用正确的编码
                command.Append("chcp 65001 > nul && "); // 设置代码页为UTF-8
                command.Append($"{svnPath} checkout \"{svnUrl}\" \"{localPath}\"");

                if (!string.IsNullOrEmpty(AppConfig.Options.SvnConfig.Username))
                {
                    command.Append($" --username \"{AppConfig.Options.SvnConfig.Username}\"");
                }

                if (!string.IsNullOrEmpty(AppConfig.Options.SvnConfig.Password))
                {
                    command.Append($" --password \"{AppConfig.Options.SvnConfig.Password}\"");
                }

                command.Append(" --non-interactive --trust-server-cert");

                var output = await ExecuteSvnCommandAsync(command.ToString());
                return true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"检出SVN项目失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 验证SVN连接
        /// </summary>
        /// <param name="repositoryUrl">SVN仓库URL</param>
        /// <returns>是否连接成功</returns>
        internal static async Task<bool> TestSvnConnectionAsync(string repositoryUrl)
        {
            try
            {
                await GetSvnDirectoriesAsync(repositoryUrl);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 获取SVN路径下的所有条目（文件和目录）
        /// </summary>
        /// <param name="svnUrl">SVN路径URL</param>
        /// <returns>条目信息列表</returns>
        internal static async Task<List<SvnItemInfo>> ListSvnPathAsync(string svnUrl)
        {
            var items = new List<SvnItemInfo>();
            try
            {
                var svnCommand = BuildSvnListCommand(svnUrl);
                var output = await ExecuteSvnCommandAsync(svnCommand);

                items = ParseSvnListOutputForItems(output, svnUrl);
            }
            catch (Exception ex)
            {
                throw new Exception($"获取SVN目录内容失败: {ex.Message}", ex);
            }
            return items;
        }

        /// <summary>
        /// 解析SVN list命令的输出以获取所有条目
        /// </summary>
        private static List<SvnItemInfo> ParseSvnListOutputForItems(string output, string repositoryUrl)
        {
            var items = new List<SvnItemInfo>();
            if (string.IsNullOrWhiteSpace(output))
                return items;

            var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var line in lines)
            {
                var trimmedLine = line.Trim();
                if (string.IsNullOrWhiteSpace(trimmedLine))
                    continue;

                var isDirectory = trimmedLine.EndsWith("/");
                var name = isDirectory ? trimmedLine.TrimEnd('/') : trimmedLine;

                if (string.IsNullOrWhiteSpace(name))
                    continue;

                items.Add(new SvnItemInfo
                {
                    Name = name,
                    Url = $"{repositoryUrl.TrimEnd('/')}/{name}",
                    ItemType = isDirectory ? SvnItemType.Directory : SvnItemType.File
                });
            }
            return items;
        }
    }

    /// <summary>
    /// SVN条目类型
    /// </summary>
    internal enum SvnItemType
    {
        File,
        Directory
    }

    /// <summary>
    /// SVN条目信息
    /// </summary>
    internal class SvnItemInfo
    {
        public string Name { get; set; } = string.Empty;
        public string Url { get; set; } = string.Empty;
        public SvnItemType ItemType { get; set; }
    }

    /// <summary>
    /// SVN项目信息
    /// </summary>
    internal class SvnProjectInfo
    {
        public string ProjectName { get; set; } = string.Empty;
        public string SvnUrl { get; set; } = string.Empty;
        public string Repository { get; set; } = string.Empty;
        public string RepositoryName { get; set; } = string.Empty;
        public DateTime LastModified { get; set; }
    }

    /// <summary>
    /// SVN目录信息
    /// </summary>
    internal class SvnDirectoryInfo
    {
        public string Name { get; set; } = string.Empty;
        public string Url { get; set; } = string.Empty;
        public DateTime LastModified { get; set; }
    }
}